//
//  ZYPurchaseSaleman.m
//  ZYPurchase
//
//  Created by wu on 2020/8/6.
//  Copyright © 2020 wu. All rights reserved.
//

#import "ZYPurchaseSaleman.h"
#import "ZYPurchaseDataBase.h"
#import "ZYPurchaseSaleman+IAP.h"
#import "ZYPurchaseLogRecorder.h"

#import <ZYNetwork/PJNetworkStation.h>


// 创建订单结果的通知
NSString *const ZYPurchaseCreateOrderComplete_Notifi = @"ZYPurchaseCreateOrderComplete_Notifi";
// 交易状态变更的通知
NSString *const ZYPurchaseTransactionStatusChanged_Notifi = @"ZYPurchaseTransactionStatusChanged_Notifi";
// 支付结束但没找到交易的通知
NSString *const ZYPurchasePurchasedWithoutTransaction_Notifi = @"ZYPurchasePurchasedWithoutTransaction_Notifi";
// 获取国家码用的商品id  ， 用一定存在的商品id即可
NSString *const ZYPurchase_CountryCodeRequest_ProductId = @"com.zhiyun.ZYFilmic_C_PrimeVIP_M";

// 用来存储是否访问过内购的标记
NSString *const ZYPurchaseIAP_Accessed_Key = @"ZYPurchaseIAP_Accessed_Key";

@interface ZYPurchaseSaleman ()

@property (nonatomic, strong) ZYPurchaseLogRecorder *logRecorder;
@property (nonatomic, assign) BOOL logEnable;

@end


//static NSString *const ZYPurchaseAPI_CreateOrder = @"/iap/createOrder";      // 创建订单
//static NSString *const ZYPurchaseAPI_VerifyReceipt = @"/iap/verifyReceipt";  // 收据校验

NSString *const ZYPurchaseAPI_CreateOrder = @"/v1/createOrder";      // 创建订单
NSString *const ZYPurchaseAPI_PayFailure = @"/v1/orderFail";           // 支付失败
NSString *const ZYPurchaseAPI_VerifyReceipt = @"/v1/appstore/verify";  // 收据校验
NSString *const ZYPurchaseAPI_Get_SubscribeStatus = @"/v1/subStatus";      // 查询订阅状态


@implementation ZYPurchaseSaleman
/// 单例
+ (instancetype)defaultSaleman{
    static dispatch_once_t onceToken;
    static ZYPurchaseSaleman *saleman = nil;
    dispatch_once(&onceToken, ^{
        saleman = [[ZYPurchaseSaleman alloc] init];
        
        saleman.logEnable = YES;
        #ifdef DEBUG
        saleman.logEnable = YES;
        #endif
    });
    return saleman;
}

/// 添加或更新 log 记录
+ (void)resetLogRecorder{
    if (![ZYPurchaseSaleman defaultSaleman].logEnable) {
        return;
    }
    if ([ZYPurchaseSaleman defaultSaleman].logRecorder) {
        [ZYPurchaseSaleman finishLogRecord];
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [ZYPurchaseSaleman defaultSaleman].logRecorder = [ZYPurchaseLogRecorder genLogRecorder];
            [[ZYPurchaseSaleman defaultSaleman] logRecord:@">>>>>>>>>>   start"];
        });
    } else {
        [ZYPurchaseSaleman defaultSaleman].logRecorder = [ZYPurchaseLogRecorder genLogRecorder];
        [[ZYPurchaseSaleman defaultSaleman] logRecord:@">>>>>>>>>>   start"];
    }
}
/// 结束一次log记录
+ (BOOL)finishLogRecord{
    if (![ZYPurchaseSaleman defaultSaleman].logEnable) {
        return NO;
    }
    if ([ZYPurchaseSaleman defaultSaleman].logRecorder) {
        [[ZYPurchaseSaleman defaultSaleman] logRecord:@"<<<<<<<<<<   finish"];
        BOOL logResult = [[ZYPurchaseSaleman defaultSaleman].logRecorder finish];
        [ZYPurchaseSaleman defaultSaleman].logRecorder = nil;
        return logResult;
    }
    return NO;
}
+ (void)logRecord:(id)content{
    [[ZYPurchaseSaleman defaultSaleman] logRecord:content];
}
- (void)logRecord:(id)content{
    if (self.logRecorder && self.logEnable) {
       [self.logRecorder record:content];
    }
}
- (void(^)(id content))logRecord{
    return ^(id content){
        [self logRecord:content];
    };
}

- (NSInteger)accessStatus{
    NSInteger retValue = NO;
    id iap_accessed_obj = [[NSUserDefaults standardUserDefaults] objectForKey:ZYPurchaseIAP_Accessed_Key];
    if (iap_accessed_obj) {
        retValue = [iap_accessed_obj integerValue];
    }
    return retValue;
}

- (instancetype)init{
    self = [super init];
    if (self) {
        _restoreStatus = ZYPurchaseIAPRestoreStatus_Accessed;
//        _restoreStatus = [self accessStatus];
        
        self.reachabilityStatus = AFNetworkReachabilityStatusUnknown;
        _database = [[ZYPurchaseDataBase alloc] init];
        
        [NSNotificationCenter.defaultCenter addObserver:self
                                               selector:@selector(networkStatusChanged)
                                                   name:AFNetworkingReachabilityDidChangeNotification
                                                 object:nil];
        if (self.restoreStatus == ZYPurchaseIAPRestoreStatus_Accessed) {
            NSLog(@"IAP:  restore start");
            [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
//            [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
        }
        [self requestCountryCodeIfNeeded:nil];
    }
    return self;
}

- (void)setTransaction_delegate:(id<ZYPurchaseTransactionDelegate>)transaction_delegate{
    _transaction_delegate = transaction_delegate;
    if (!transaction_delegate) {
        self.priceRequest = nil;
        self.priceRequestHandler = nil;
        self.invalidProductIdentifiers = nil;
    }
}

/// 是否访问过IAP数据
+ (BOOL)restoreStatusAccessed{
    return (ZYPurchaseSaleman.defaultSaleman.restoreStatus == ZYPurchaseIAPRestoreStatus_Accessed);
}

- (void)setRestoreStatus:(ZYPurchaseIAPRestoreStatus)restoreStatus{
    if ((_restoreStatus != restoreStatus) && (restoreStatus != ZYPurchaseIAPRestoreStatus_Asking)) {
        [[NSUserDefaults standardUserDefaults] setObject:@(restoreStatus) forKey:ZYPurchaseIAP_Accessed_Key];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
    _restoreStatus = restoreStatus;
}

// 查询
+ (void)restoreIAPPurchaseInfo{
//    [ZYPurchaseSaleman.defaultSaleman restoreIAPPurchaseInfo];
}
- (void)restoreIAPPurchaseInfo{
    if (self.restoreStatus == ZYPurchaseIAPRestoreStatus_Accessed) {
        [self responseRestoreStatusForDelegate:self.restoreStatus];
        return;
    }
    self.restoreStatus = ZYPurchaseIAPRestoreStatus_Asking;
    [self responseRestoreStatusForDelegate:self.restoreStatus];
    
    NSLog(@"IAP:  restore start");
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(40.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        if (self.restoreStatus == ZYPurchaseIAPRestoreStatus_Asking) {
            self.restoreStatus = ZYPurchaseIAPRestoreStatus_AccessedFail;
            [self responseRestoreStatusForDelegate:self.restoreStatus];
        }
    });
}

- (void)responseRestoreStatusForDelegate:(ZYPurchaseIAPRestoreStatus)restoreStatus{
    if (self.transaction_delegate && [self.transaction_delegate respondsToSelector:@selector(restoreStatusAccessedChanged:)]) {
        [self.transaction_delegate restoreStatusAccessedChanged:restoreStatus];
    }
}

/// 请求国家码
+ (void)requestCountryCodeIfNeeded:(nullable void (^)(NSString *countryCode))complete{
    [ZYPurchaseSaleman.defaultSaleman requestCountryCodeIfNeeded:complete];
}
- (void)requestCountryCodeIfNeeded:(nullable void (^)(NSString *countryCode))complete{
    if (@available(iOS 13, *) && (SKPaymentQueue.defaultQueue.storefront.countryCode.zy_isValuable)) {
        self.countryCode = SKPaymentQueue.defaultQueue.storefront.countryCode;
        if (complete) {
            complete(self.countryCode);
        }
        return;
    }
    if (self.countryCode.zy_isValuable) {
        if (complete) {
            complete(self.countryCode);
        }
        return;
    }
    ZYProductsRequest *request = [[ZYProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:ZYPurchase_CountryCodeRequest_ProductId]];
    request.delegate = self;
    [request start];
    NSLog(@"IAP: 国家码请求开始");
    if (complete) {
        self.countryCodeRequestBlock = complete;
    }
}

- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue{
    NSLog(@"IAP: Restore 查询没有数据，restore ask 结束");
    if (self.restoreStatus != ZYPurchaseIAPRestoreStatus_Accessed) {
        self.restoreStatus = ZYPurchaseIAPRestoreStatus_Accessed;
        
        [self responseRestoreStatusForDelegate:self.restoreStatus];
    }
}

- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error{
    NSLog(@"IAP: Restore 失败，restore ask 结束, %@", error);
    if (self.restoreStatus != ZYPurchaseIAPRestoreStatus_Accessed) {
        self.restoreStatus = ZYPurchaseIAPRestoreStatus_AccessedFail;
        
        [self responseRestoreStatusForDelegate:self.restoreStatus];
    }
}

- (void)networkStatusChanged{
    if (!ZYPurchaseSaleman.restoreStatusAccessed) {
        return;
    }
    AFNetworkReachabilityManager *netWorkManager = [AFNetworkReachabilityManager sharedManager];
    AFNetworkReachabilityStatus status = netWorkManager.networkReachabilityStatus;
    if ((self.reachabilityStatus == status) && (self.reachabilityStatus != AFNetworkReachabilityStatusUnknown)) {
        return;
    }
    self.reachabilityStatus = status;
    if (status == AFNetworkReachabilityStatusReachableViaWWAN ||
        status == AFNetworkReachabilityStatusReachableViaWiFi) {
        [self uploadUnVerifyReceiptIfNeededInSilence:nil];
    }
}

/// 支付方式是否支持
+ (BOOL)supportPaymentMethod:(ZYPurchasePaymentMethod)paymentMethod{
    if (paymentMethod == ZYPurchasePaymentMethod_IAP) {
        return SKPaymentQueue.canMakePayments;
    }
    return NO;
}

/// 设置设备唯一标识符
+ (void)setupDeviceUUID:(NSString *)uuid{
    ZYPurchaseSaleman.defaultSaleman.deviceUUID = uuid;
}

/// 重置客户信息
/// @param customerId 用户 id
/// @param customerToken 用户 token
+ (void)resetCustomerInfo:(nonnull NSString *)customerId
            customerToken:(nonnull NSString *)customerToken{
    if (!customerId.zy_isValuable ||
        !customerToken.zy_isValuable) {
        return;
    }
    ZYPurchaseSaleman.defaultSaleman.customerId = customerId;
    ZYPurchaseSaleman.defaultSaleman.customerToken = customerToken;
}



+ (NSString *)bundleIdString{
    id bundleIDObj = [NSBundle.mainBundle.infoDictionary objectForKey:@"CFBundleIdentifier"];
    return bundleIDObj?bundleIDObj:@"";
}

/// 获取订阅状态
+ (void)getCurrentUserSubscribeStatus:(void(^)(BOOL success, id info))complete{
    NSString *customerId = ZYPurchaseSaleman.defaultSaleman.customerId;
    NSString *customerToken = ZYPurchaseSaleman.defaultSaleman.customerToken;
    NSDictionary *params = @{@"userid":customerId,
                             @"user_token":customerToken};
    
    NSString *url = ZYPurchaseSaleman.formatPurchageUrlString(ZYPurchaseAPI_Get_SubscribeStatus);
    [PJNetworkStation GET:url params:params result:^(BOOL success, id info) {
        if (success && [info isKindOfClass:[NSDictionary class]]) {
            NSDictionary *dict = info;
            NSArray *sub_arr;
            if ([dict.allKeys containsObject:@"data"]) {
                id dataObj = [dict objectForKey:@"data"];
                if (dataObj && [dataObj isKindOfClass:[NSArray class]]) {
                    if (((NSArray *)dataObj).count > 0) {
                        sub_arr = dataObj;
                    }
                }
            }
            if (sub_arr) {
                complete(YES, sub_arr);
            } else {
                complete(NO, @"Current user have no subscribe");
            }
        } else {
            complete(NO, info);
        }
    }];
}

/// 判断是否是订阅产品标识
+ (BOOL)isSubscribe:(nonnull NSString *)productIdentifier{
    if (productIdentifier && (productIdentifier.length > 0)) {
        NSArray *sub_arr = [productIdentifier componentsSeparatedByString:@"_"];
        if (sub_arr.count > 1) {
            NSString *categoryStr = sub_arr[1];
            return [categoryStr.uppercaseString isEqualToString:@"C"];
        }
    }
    return NO;
}

#pragma mark - 创建订单信息
+ (void)createOrder:(nonnull NSArray <NSDictionary *>*)productInfo
          isDigital:(BOOL)isDigital
           complete:(nonnull void (^)(BOOL success, id info))complete{
    NSString *customerId = ZYPurchaseSaleman.defaultSaleman.customerId;
    NSString *customerToken = ZYPurchaseSaleman.defaultSaleman.customerToken;
    if (!productInfo || !customerId || (customerId.length == 0) || (productInfo.count == 0)) {
        // 缺少必要信息
        complete(NO, ZYPurchaseSaleman.formatErrorResponse(70001));
        [ZYPurchaseSaleman logRecord:[NSString stringWithFormat:@"创建订单失败：70001"]];
        return;
    }
    NSDictionary *productDict_first = productInfo.firstObject;
    if (![productDict_first.allKeys containsObject:@"productIdentifier"]) {
        // 缺少必要信息
        complete(NO, ZYPurchaseSaleman.formatErrorResponse(70001));
        [ZYPurchaseSaleman logRecord:[NSString stringWithFormat:@"创建订单失败：70001"]];
        return;
    }
    /// 第二步：服务器创建订单，产生订单信息
    NSDictionary *productDict = ZYPurchaseSaleman.defaultSaleman.products.firstObject;
    NSString *productId = [productDict zy_stringForKey:@"productId"];
    
    NSString *transactionIdString;
    NSArray *transactionIds = [ZYPurchaseSaleman.defaultSaleman.database allOriginTransactionIdInApple];
    if (transactionIds.count > 0) {
        transactionIdString = [transactionIds componentsJoinedByString:@","];
    }
    NSString *countryCode = [ZYPurchaseSaleman defaultSaleman].countryCode;
    NSMutableDictionary *params = @{@"userid":customerId,
                                    @"user_token":customerToken,
                                    @"platform_product_id":productId.zy_isValuable?productId:@"",
                                    @"packageName":[ZYPurchaseSaleman bundleIdString],
                                    @"country_code":countryCode.zy_isValuable?countryCode:@"",
                                    @"deviceId":ZYPurchaseSaleman.defaultSaleman.deviceUUID}.mutableCopy;
    if (transactionIdString && productId.zy_isValuable && [ZYPurchaseSaleman isSubscribe:productId]) {
        params[@"purchase_ids"] = transactionIdString;
    }
    if ([ZYPurchaseSaleman defaultSaleman].priceRequest) {
        for (NSInteger idx = 0; idx < [ZYPurchaseSaleman defaultSaleman].priceRequest.productsInfo.count; idx++) {
            NSDictionary *proDict = [ZYPurchaseSaleman defaultSaleman].priceRequest.productsInfo[idx];
            NSString *pro_id = [proDict zy_stringForKey:@"third_product_id"];
            NSString *productIden = [productInfo.firstObject zy_stringForKey:@"productIdentifier"];
            if ([pro_id isEqualToString:productIden] &&
                ([proDict.allKeys containsObject:@"price"])) {
                NSString *currencySymbol = [proDict zy_stringForKey:@"currencySymbol"];
                NSString *currencyCode = [proDict zy_stringForKey:@"currencyCode"];
                double price = [[proDict objectForKey:@"price"] doubleValue];
                params[@"country_code_price"] = @(price*100);
                
                NSString *coutryCode = [ZYPurchaseSaleman defaultSaleman].countryCode;
                coutryCode = coutryCode.zy_isValuable?coutryCode:@"";
                params[@"country_code_price_show"] = [NSString stringWithFormat:@"%@%.2f", currencySymbol, price];
                break;
            }
        }
    }
    
    NSString *url = ZYPurchaseSaleman.formatPurchageUrlString(ZYPurchaseAPI_CreateOrder);
    [PJNetworkStation POST:url params:params result:^(BOOL success, id info) {
        NSLog(@"IAP: 创建订单接口 params:%@, 返回结果：%@, info: %@", params, success?@"成功":@"失败", info);
        
        [ZYPurchaseSaleman logRecord:@"创建参数："];
        [ZYPurchaseSaleman logRecord:params];
        [ZYPurchaseSaleman logRecord:[NSString stringWithFormat:@"订单结果： %@", success?@"成功":@"失败"]];
        [ZYPurchaseSaleman logRecord:info];
        
        NSString *orderIdStr = nil;
        if (success && [info isKindOfClass:[NSDictionary class]]) {
            NSDictionary *dataDict = info;
            if ([dataDict.allKeys containsObject:@"orderSN"]) {
                id orderIdObj = dataDict[@"orderSN"];
                if ([orderIdObj isKindOfClass:[NSString class]]) {
                    orderIdStr = orderIdObj;
                }
            }
            if (orderIdStr) {
                double timestamp = [NSDate.date timeIntervalSince1970];
                
                ZYPurchaseOrderModel *retModel = [[ZYPurchaseOrderModel alloc] init];
                retModel.orderId = orderIdStr;
                retModel.isDigital = isDigital;
                retModel.userId = customerId;
                retModel.paymentStatus = ZYPurchaseOrderPaymentStatus_Unpaid;
                retModel.createTime = timestamp;
                retModel.updateTime = timestamp;
                retModel.productInfo = productInfo;
                complete(YES, retModel);
            } else {
                // 后台未返回orderSN
                complete(NO, ZYPurchaseSaleman.formatErrorResponse(70006));
            }
        } else {
            complete(NO, info);
        }
    }];
}

+ (void)resetPurchaseHost:(nonnull NSString *)host{
    [ZYPurchaseSaleman defaultSaleman].serverHost = host;
}

+ (NSString *(^)(NSString *path))formatPurchageUrlString{
    return ^(NSString *path){
        return [[ZYPurchaseSaleman defaultSaleman].serverHost stringByAppendingString:path];
    };
}
+ (NSDictionary *)allErrorInfo{
    NSDictionary *createOrder = @{@(70001):@"缺少必要信息",
                                  @(70002):@"App版本不支持",
                                  @(70003):@"创建订单失败",
                                  @(70004):@"未找到商品",
                                  @(70005):@"无效的产品标识",
                                  @(70006):@"后台未返回orderSN",
                                  @(70007):@"此设备不支持内购",
                                  @(70050):@"订单无收据",
                                  @(70051):@"收据校验不通过",
                                  @(70052):@"收据校验中断，网络原因或服务器宕机等服务器自身问题",
                                  @(70053):@"当前Apple 账号订阅关系已与其他ZYCami账号绑定",
                                  @(70098):@"已取消支付",
                                  @(70099):@"存在未完成的交易",
                                  @(70100):@"操作太快",
                                  @(70101):@"网络未连接，无法发起购买",
                                  @(70102):@"创建订单超时",
    };
    
    return createOrder;
}

+ (NSDictionary *)formatErrorDict:(NSInteger)errorCode{
    NSNumber *keyObj = @(errorCode);
    NSDictionary *allErrorDict = [self allErrorInfo];
    if ([allErrorDict.allKeys containsObject:keyObj]) {
        return @{@"errcode":keyObj, @"errmsg":allErrorDict[keyObj]};
    }
    return @{@"errcode":@(errorCode), @"errmsg":@"未知错误"};
}

+ (NSDictionary *(^)(NSInteger errorCode))formatErrorResponse{
    return ^(NSInteger errorCode){
        return [self formatErrorDict:errorCode];
    };
}

@end


@implementation NSString (ZYPurchageExtension)

// 是否可用
- (BOOL)zy_isValuable{
    return (self && [self isKindOfClass:[NSString class]] && (self.length>0));
}

@end

@implementation NSDictionary (ZYPurchageSafety)

// 检测该key是否z可以正常存取
- (BOOL)probeKeyIsAllowed:(NSString *)key{
    if (!self || !key) {
        return NO;
    }
    if (key.length == 0) {
        return NO;
    }
    if (self.allKeys.count == 0) {
        return NO;
    }
    BOOL exist = [self.allKeys containsObject:key];
    if (exist) {
        id keyObj = [self valueForKey:key];
        if ([keyObj isKindOfClass:[NSNull class]]) {
            return NO;
        }
    }
    return exist;
}

/**
 获取字符串
 */
- (NSString *)zy_stringForKey:(NSString *)key{
    if (![self probeKeyIsAllowed:key]) {
        return nil;
    }
    id keyObj = [self valueForKey:key];
    if ([keyObj isKindOfClass:[NSString class]]) {
        return keyObj;
    }
    return nil;
}

@end

@implementation ZYProductsRequest

@end
